package edu.idp.tools;

import edu.idp.client.InterDrawPanel;
import edu.idp.server.database.Database;
import edu.idp.shared.StoredObject;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.DataInputStream;
import java.io.EOFException;
import java.lang.reflect.Array;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.Hashtable;
import java.util.Vector;
//import java.util.*;

public class ImageDisplay extends JFrame implements ActionListener, MouseListener, ListSelectionListener, DocumentListener {

    private JList imageList = null;
    private JList objectList = null;

    private JButton openButton = null;
    private JButton refreshButton = null;
    private JScrollPane scrollPane = null;
    private JScrollPane objScrollPane = null;

    private Vector actionListeners = null;
    private String selectedImage = null;
    private boolean solarisWorkaround = false;
    private Hashtable objectTypes = new Hashtable();
    private Connection con = null;
    private InterDrawPanel idpp = null;
    private StoredObject[] storedObjects = null;
    private JButton openAll = null;
    private JButton openOne = null;
    private JButton clearAll = null;
    private JButton remove = null;
    private boolean[] inserted;
    private Hashtable removalDate = new Hashtable();
    private JCheckBox insertDeleted = null;
    private boolean do_insert = false;
    private JFrame myframe = null;

    public ImageDisplay(InterDrawPanel idpp, JFrame myframe) {

        this.myframe = myframe;
        this.idpp = idpp;
        String osName = System.getProperty("os.name");

        solarisWorkaround = (osName != null && (osName.indexOf("Solaris") != -1 || osName.indexOf("Irix") != -1));

        openButton = new JButton("Open");
        openButton.setDefaultCapable(true);

        refreshButton = new JButton("Refresh");
        openAll = new JButton("Add Up To");
        openOne = new JButton("Add Selected");
        clearAll = new JButton("Clear");
        remove = new JButton("Remove");
        insertDeleted = new JCheckBox("Insert Removed");

        int diff = 0;
        if (solarisWorkaround)
            diff = 20;

        objectTypes.put(new Integer(0), "FREEHAND");
        objectTypes.put(new Integer(1), "LINE");
        objectTypes.put(new Integer(2), "ELLIPSE");
        objectTypes.put(new Integer(3), "RECTANGLE");
        objectTypes.put(new Integer(4), "ANIMATED");
        objectTypes.put(new Integer(5), "AIRBRUSH");

        imageList = new JList(getImageNames());
        scrollPane = new JScrollPane(imageList);
        objectList = new JList();
        objScrollPane = new JScrollPane(objectList);

        getContentPane().setLayout(null);
        scrollPane.setBounds(5, 5, 250, 155);
        openButton.setBounds(5, 165 - diff, 80 + diff, 30);
        refreshButton.setBounds(175, 165 - diff, 80 + diff, 30);
        objScrollPane.setBounds(5, 200 - diff, 475 + diff, 300);

        openOne.setBounds(5, 505 - diff, 150 + diff, 30);
        openAll.setBounds(330, 505 - diff, 150 + diff, 30);
        clearAll.setBounds(5, 540 - diff, 150 + diff, 30);
        remove.setBounds(330, 540 - diff, 150 + diff, 30);
        insertDeleted.setBounds(170, 540 - diff, 150 + diff, 30);

        getContentPane().add(scrollPane);
        getContentPane().add(openButton);
        getContentPane().add(refreshButton);
        getContentPane().add(objScrollPane);
        getContentPane().add(openOne);
        getContentPane().add(openAll);
        getContentPane().add(clearAll);
        getContentPane().add(remove);
        getContentPane().add(insertDeleted);

        this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        this.getRootPane().setDefaultButton(openButton);

        openButton.addActionListener(this);
        refreshButton.addActionListener(this);
        imageList.addMouseListener(this);
        imageList.addListSelectionListener(this);
        objectList.addListSelectionListener(this);
        objectList.addMouseListener(this);
        openAll.addActionListener(this);
        openOne.addActionListener(this);
        clearAll.addActionListener(this);
        remove.addActionListener(this);
        insertDeleted.addActionListener(this);
        this.addActionListener(this);

        this.setResizable(true);
        this.setTitle("Image Selection");
        this.setSize(500 + diff, 600 + ((diff == 0) ? diff : diff - 5));
    }

    public void setSelected(String image, boolean update) {
        this.selectedImage = image;
//    if (update)
//      imageText.setText(image);
    }

    public String getSelected() {
        return this.selectedImage;
    }

    private void close() {
        this.dispose();
    }

    private String[] createObjectList(StoredObject[] objs) {
        String[] retString = null;
        if (objs == null || Array.getLength(objs) == 0) {
            retString = new String[1];
            return retString;
        }
        int size = Array.getLength(objs);

        retString = new String[size];
        for (int i = 0; i < size; i++) {
            retString[i] = (String) objectTypes.get(new Integer(objs[i].getType()));
            for (int j = 0; j < 20 - retString[i].length(); j++)
                retString[i] += " ";

            Timestamp tm = new Timestamp(objs[i].getDate());
            retString[i] += tm.toString();
            if (removalDate.containsKey(objs[i])) {
                retString[i] += "   ";
                retString[i] += ((Timestamp) removalDate.get(objs[i])).toString();
            }
        }

        return retString;
    }

    private StoredObject[] getObjects(String image) {
        if (con == null) {
            try {
                Class.forName(Database.DRIVER);
                con = DriverManager.getConnection(Database.URL, Database.USER, Database.PASSWORD);
            }
            catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "cannot connect to database");
                ex.printStackTrace();
                //String[] ret= new String[1];
                return null;
            }
            System.out.println("Connected to database");
        }

        StoredObject[] retData = null;
        try {
            PreparedStatement psRetrieveSome = con.prepareStatement("SELECT insert_dt, removal_dt, data_str FROM objects where image_nm = '" + image + "' order by insert_dt");

            ResultSet rs = psRetrieveSome.executeQuery();

            Vector ll = new Vector();

            removalDate.clear();

            while (rs.next()) {

                DataInputStream dis = new DataInputStream(rs.getBinaryStream("data_str"));
                String retString = new String();
                try {
                    while (true) {
                        retString += dis.readChar();
                    }
                }
                catch (EOFException e) {
                }
                StoredObject so = new StoredObject(retString);
                ll.add(so);
                Timestamp st = rs.getTimestamp("removal_dt");
                if (st != null)
                    removalDate.put(so, st);
            }

            int size = ll.size();
            retData = new StoredObject[size];
            inserted = new boolean[size];

            for (int i = 0; i < size; i++) {
                inserted[i] = false;
                retData[i] = (StoredObject) ll.elementAt(i);
            }
        }
        catch (Exception e) {
            JOptionPane.showMessageDialog(this, "error database");
            e.printStackTrace();

            return null;
        }
        return retData;
    }

    private String[] getImageNames() {
        if (con == null) {
            try {
                Class.forName(Database.DRIVER);
                con = DriverManager.getConnection(Database.URL, Database.USER, Database.PASSWORD);
            }
            catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "cannot connect to database");
                ex.printStackTrace();
                String[] ret = new String[1];
                return ret;
            }
            System.out.println("Connected to database");
        }

        String[] retData;
        try {
            PreparedStatement psRetrieveSome = con.prepareStatement("SELECT image_nm FROM objects group by image_nm order by image_nm");

            ResultSet rs = psRetrieveSome.executeQuery();

            //int size = rs.getFetchSize();
            Vector ll = new Vector();
//      retData = new String[size];
            //int i = 0;
            while (rs.next()) {
                ll.addElement(rs.getString("image_nm"));
                //retData[i++] =
            }

            int size = ll.size();
            if (size == 0)
                retData = new String[1];
            else {
                retData = new String[size];

            }

            for (int i = 0; i < size; i++) {
                retData[i] = (String) ll.elementAt(i);
            }
        }
        catch (Exception e) {
            JOptionPane.showMessageDialog(this, "error database");
            e.printStackTrace();
            String[] ret = new String[1];
            return ret;
        }
        return retData;
    }

    /*
             int index = objectList.locationToIndex(e.getPoint());
           System.out.println("Double clicked on Item " + index);
           idpp.saveExternalObject(storedObjects[index]);
           idpp.restoreAll();
    */
/**
 * ****************************************************
 * ActionListener
 * *****************************************************
 */

    public void actionPerformed(ActionEvent e) {
        Object o = e.getSource();

        if (o == openButton)
            actionPerformed_OpenButton();
        else if (o == refreshButton)
            actionPerformed_RefreshButton();
        else if (o == insertDeleted) {
            if (do_insert)
                do_insert = false;
            else
                do_insert = true;
        }
        else if (o == openOne) {
            int index = objectList.getSelectedIndex();
            if (index == -1)
                return;
            if (inserted[index])
                return;
            System.out.println("Opening item " + index);
            inserted[index] = true;
            idpp.saveExternalObject(storedObjects[index]);
            idpp.restoreAll();
        }
        else if (o == openAll) {
            int index = objectList.getSelectedIndex();
            if (index == -1)
                return;
            idpp.removeAll();
            System.out.println("Opening item " + index);
            for (int i = index; i >= 0; i--) {
                inserted[i] = true;
                if (do_insert || !removalDate.containsKey(storedObjects[i]))
                    idpp.saveExternalObject(storedObjects[i]);
                else
                    System.out.println("did not insert object");
            }
            idpp.restoreAll();
        }
        else if (o == clearAll) {
            idpp.removeAll();
            for (int i = 0; i < Array.getLength(inserted); i++)
                inserted[i] = false;
        }
        else if (o == remove) {
            int index = objectList.getSelectedIndex();
            if (index == -1)
                return;
            inserted[index] = false;
            idpp.removeExternalObject(storedObjects[index]);
            idpp.restoreAll();
        }
        else if (o == this) {
            if (e.getID() == 0) {
                System.out.println("update object list!");
                idpp.removeAll();
                storedObjects = getObjects(e.getActionCommand());
                String[] objects = createObjectList(storedObjects);
                if (objects != null)
                    objectList.setListData(objects);
                else {
                    String[] tmp = new String[1];
                    objectList.setListData(tmp);
                    //objectList.setListData(objects);
                }
            }
            else
                System.out.println("some random action performed.");
        }
    }

    private void actionPerformed_OpenButton() {
//    System.out.println("selected :"+getSelected());
        String img = getSelected();
        if (img != null) {
            myframe.setTitle("Image: " + img);
            processActionEvent(new ActionEvent(this, 0, img));
        }
//    close();
    }

    private void actionPerformed_CancelButton() {
        processActionEvent(new ActionEvent(this, 0, null));
        close();
    }

    private void actionPerformed_RefreshButton() {
        imageList.setListData(getImageNames());
    }

    /**
     * ****************************************************
     * ListSelectionListener
     * *****************************************************
     */

    public void valueChanged(ListSelectionEvent e) {
        setSelected((String) imageList.getSelectedValue(), true);
//    System.out.println((String)imageList.getSelectedValue());
    }

    /**
     * ****************************************************
     * MouseListener
     * *****************************************************
     */

    public void mouseClicked(MouseEvent e) {
        if (e.getClickCount() == 2) {
            Object o = e.getSource();

            if (o == imageList) {
                int index = imageList.locationToIndex(e.getPoint());
                setSelected((String) imageList.getSelectedValue(), true);
                actionPerformed_OpenButton();
            }
            else if (o == objectList) {
                int index = objectList.locationToIndex(e.getPoint());
                if (inserted[index])
                    return;
                inserted[index] = true;
                System.out.println("Double clicked on Item " + index);
                idpp.saveExternalObject(storedObjects[index]);
                idpp.restoreAll();
            }
        }
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseReleased(MouseEvent e) {
    }

    /**
     * ***********************************************
     * DocumentListener
     * ************************************************
     */

    public void changedUpdate(DocumentEvent e) {
        actionPerformed_imageText();
    }

    public void insertUpdate(DocumentEvent e) {
        actionPerformed_imageText();
    }

    public void removeUpdate(DocumentEvent e) {
        actionPerformed_imageText();
    }

    private void actionPerformed_imageText() {
//    imageList.clearSelection();
//    setSelected(imageText.getText(), false);
    }

    /**
     * ***********************************************
     * Action event stuff
     * ************************************************
     */

    public synchronized void addActionListener(ActionListener l) {
        if (l == null)
            return;
        if (actionListeners == null)
            actionListeners = new Vector();

        actionListeners.add(l);
    }

    public synchronized void removeActionListener(ActionListener l) {
        if (l == null || actionListeners == null || actionListeners.size() <= 0)
            return;

        actionListeners.remove(l);

    }

    protected void processActionEvent(ActionEvent e) {
        if (actionListeners != null) {
            for (int i = 0; i < actionListeners.size(); i++)
                ((ActionListener) actionListeners.elementAt(i)).actionPerformed(e);
        }
    }


}


